package com.itzyf.pokemondata.service

import android.app.IntentService
import android.content.Context
import android.content.Intent
import android.util.Log
import com.avos.avoscloud.*
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.itzyf.pokemondata.BuildConfig
import com.itzyf.pokemondata.R
import com.itzyf.pokemondata.bean.*
import okhttp3.Callback
import okhttp3.OkHttpClient
import okhttp3.Request
import org.litepal.LitePal
import java.lang.reflect.Type


class DataIntentService : IntentService("DataIntentService") {
    private var configDo: DbConfigDo? = null
    override fun onHandleIntent(intent: Intent?) {
        Log.d("DataIntentService", "启动数据服务")
        val sp = getSharedPreferences("config", Context.MODE_PRIVATE)
        configDo = LitePal.findFirst(DbConfigDo::class.java)

        //如果当前版本为13，则强制重新读取数据
        if (!sp.getBoolean(BuildConfig.DATA_VERSION, false)) {
            LitePal.deleteAll(DbExclusive::class.java)
            LitePal.deleteAll(DbPokemon::class.java)
            LitePal.deleteAll(DbComprehensiveDo::class.java)
            LitePal.deleteAll(DbFestivalEnvoyDo::class.java)
            LitePal.deleteAll(DbCharacteristicDo::class.java)
            LitePal.deleteAll(DbSkillDo::class.java)
            LitePal.deleteAll(DbSuperSkillDo::class.java)
            LitePal.deleteAll(DbPropDo::class.java)
            sp.edit().putBoolean(BuildConfig.DATA_VERSION, true).apply()
            configDo?.delete()
            configDo = null
        }

        if (!sp.getBoolean("init85", false)) {
            LitePal.deleteAll(DbPropDo::class.java)
            sp.edit().putBoolean("init85", true).apply()
            configDo?.prop = 1
            saveProp()
        }

        //如果已经有数据，就改为获取有无新数据
        if (LitePal.count(DbExclusive::class.java) > 0) {
            Log.d("DataIntentService", "从网络读取配置")
            readConfig()
        } else {
            //读取本地数据
            rawReader()
        }
    }


    /**
     *
     * 读取本地配置,判断是否需要更新
     */
    private fun readConfig() {
        val query = AVQuery<AVObject>("config")
        query.getInBackground("5ca2bfe0a91c93007245e8a0", object : GetCallback<AVObject>() {
            override fun done(obj: AVObject?, e: AVException?) {
                if (obj != null) {
                    val config = ConfigDo(obj)
                    println(config.toString())
                    config.let {
                        if (configDo == null) {
                            configDo = DbConfigDo()
                        }
                        configDo?.let { configDo1 ->
                            if (it.exclusive > configDo1.exclusive) {
                                updateExclusive()
                            }
                            if (it.pokemon > configDo1.pokemon) {
                                updatePokemon()
                            }
                            if (it.comprehensiveType > configDo1.comprehensiveType) {
                                updateComprehensiveType()
                            }
                            if (it.comprehensive > configDo1.comprehensive) {
                                updateComprehensive()
                            }
                            if (it.festivalEnvoy > configDo1.festivalEnvoy) {
                                updateFestivalEnvoy()
                            }
                            if (it.skill > configDo1.skill) {
                                updateSkill()
                            }
                            if (it.superSkill > configDo1.superSkill) {
                                updateSuperSkill()
                            }
                            if (it.characteristic > configDo1.characteristic) {
                                updateCharacteristic()
                            }
                            if (it.prop > configDo1.prop) {
                                updateProp()
                            }

                            configDo1.characteristic = it.characteristic
                            configDo1.comprehensive = it.comprehensive
                            configDo1.comprehensiveType = it.comprehensiveType
                            configDo1.exclusive = it.exclusive
                            configDo1.festivalEnvoy = it.festivalEnvoy
                            configDo1.pokemon = it.pokemon
                            configDo1.skill = it.skill
                            configDo1.superSkill = it.superSkill
                            configDo1.prop = it.prop
                            if (configDo1.id > 0) {
                                configDo1.update(configDo1.id)
                            } else {
                                configDo1.save()
                            }

                            if (it.notice.isNotEmpty()) {
                                val sp = getSharedPreferences("config", Context.MODE_PRIVATE)
                                sp.edit().putString("notice", it.notice).apply()
                                val intent = Intent()
                                intent.action = "loading"
                                intent.putExtra("notice", "notice")
                                sendBroadcast(intent)
                            }
                            return
                        }
                    }
                }
            }

        })

//        5ca2bfe0a91c93007245e8a0
//        httpGet("https://ityuanfeng.gitee.io/json/config.json", object : Callback {
//            override fun onFailure(call: Call, e: IOException) {
//                Log.d("DataIntentService", "异常")
//                println(e.message)
//            }
//
//            override fun onResponse(call: Call, response: Response) {
//                Log.d("DataIntentService", "请求成功" + response.toString())
//                if (!response.isSuccessful) {
//                    return
//                }
//                val config = Gson().fromJson(response.body()?.string(), ConfigDo::class.java)
//                println(config.toString())
//
//            }
//
//        })
    }


    private fun httpGet(url: String, callback: Callback) {
        Thread(Runnable {
            val okHttpClient = OkHttpClient()
            val request = Request.Builder().removeHeader("User-Agent")
                .addHeader(
                    "User-Agent",
                    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36"
                ).url(url).build()
            okHttpClient.newCall(request).enqueue(callback)
        }).start()
    }

    private fun rawReader() {
        val it = Intent()
        it.action = "loading"
        it.putExtra("loading", 1)

        sendBroadcast(it)
        LitePal.deleteAll(DbComprehensiveTypeDo::class.java)

        Log.d("DataIntentService", "从raw读取数据")
        //读取专属
        saveExclusive()
        //读取精灵数据
        savePokemon()
        //离线缓存综合数据
        saveComprehensive()

        saveFestivalEnvoy()
        //读取Z招式
        saveSuperSkill()
        //读取性格表
        saveCharacteristic()
        //读取技能
        saveSkill()

        saveProp()
        //读取配置，并更新数据
        readConfig()

        it.putExtra("loading", -1)
        sendBroadcast(it)
    }

    private fun saveComprehensive() {
        LitePal.deleteAll(DbComprehensiveDo::class.java)
        val comprehensiveList = readJson<List<ComprehensiveJsonDo>>(
            R.raw.comprehensive,
            object : TypeToken<List<ComprehensiveJsonDo>>() {}.type
        )
        for (ex in comprehensiveList) {
            val bean = DbComprehensiveDo()
            bean.content = ex.content
            bean.createdAt = ex.createdAt
            bean.httpUrl = ex.httpUrl
            bean.imageUrl = ex.imageUrl
            bean.name = ex.name
            bean.objectId = ex.objectId
            bean.type = ex.type
            bean.updatedAt = ex.updatedAt
            bean.setcTypeId(ex.cType?.objectId)
            bean.save()
        }
    }

    private fun updateComprehensive() {
        val dbExclusive = LitePal.order("updatedAt desc").findFirst(DbComprehensiveDo::class.java)
        val exclusive = AVQuery<AVObject>("comprehensive")
        if (dbExclusive != null) {
            exclusive.whereGreaterThan("updatedAt", dbExclusive.updatedAt)
        }

        exclusive.findInBackground(object : FindCallback<AVObject>() {
            override fun done(avObjects: MutableList<AVObject>?, e: AVException?) {
                e?.printStackTrace()
                if (avObjects == null)
                    return
                for (avObject in avObjects) {
                    val findFirst = LitePal.where("objectId = ?", avObject.objectId)
                        .findFirst(DbComprehensiveDo::class.java)

                    val db = DbComprehensiveDo()
                    db.content = avObject.getString("content")
                    db.createdAt = avObject.createdAt
                    db.httpUrl = avObject.getString("httpUrl")
                    db.imageUrl = avObject.getString("imageUrl")
                    db.name = avObject.getString("name")
                    db.objectId = avObject.objectId
                    db.type = avObject.getInt("type")
                    db.updatedAt = avObject.updatedAt
                    db.setcTypeId(avObject.getAVObject<AVObject>("cType")?.objectId)
                    if (findFirst == null) {
                        db.save()
                    } else {
                        db.update(findFirst.id)
                    }
                }
            }

        })
    }

    private fun updateComprehensiveType() {

        val dbComprehensiveTypeDo =
            LitePal.order("updatedAt desc").findFirst(DbComprehensiveTypeDo::class.java)
        val exclusive = AVQuery<AVObject>("comprehensiveType")
        if (dbComprehensiveTypeDo != null) {
            exclusive.whereGreaterThan("updatedAt", dbComprehensiveTypeDo.updatedAt)
        }
        exclusive.findInBackground(object : FindCallback<AVObject>() {
            override fun done(avObjects: MutableList<AVObject>?, e: AVException?) {
                e?.printStackTrace()
                if (avObjects == null)
                    return
                for (avObject in avObjects) {
                    val findFirst = LitePal.where("objectId = ?", avObject.objectId)
                        .findFirst(DbComprehensiveTypeDo::class.java)

                    val db = DbComprehensiveTypeDo(
                        avObject.createdAt,
                        avObject.getString("name"),
                        avObject.objectId,
                        avObject.updatedAt
                    )
                    if (findFirst == null) {
                        db.save()
                    } else {
                        db.update(findFirst.id)
                    }
                }
            }
        })
    }

    private fun updateExclusive() {
        val dbExclusive = LitePal.order("updatedAt desc").findFirst(DbExclusive::class.java)
        val exclusive = AVQuery<AVObject>("exclusive")
        if (dbExclusive != null) {
            exclusive.whereGreaterThan("updatedAt", dbExclusive.updatedAt)
        }

        exclusive.findInBackground(object : FindCallback<AVObject>() {
            override fun done(avObjects: MutableList<AVObject>?, e: AVException?) {
                e?.printStackTrace()
                if (avObjects == null)
                    return
                for (avObject in avObjects) {
                    val findFirst = LitePal.where("objectId = ?", avObject.objectId)
                        .findFirst(DbExclusive::class.java)

                    val pokemonName = avObject.getString("pokemonName")
                    val hp = avObject.getInt("hp")
                    val pa = avObject.getInt("pa")
                    val pd = avObject.getInt("pd")
                    val sa = avObject.getInt("sa")
                    val sd = avObject.getInt("sd")
                    val speed = avObject.getInt("speed")

                    val db = DbExclusive(
                        avObject.createdAt,
                        avObject.getString("effect"),
                        hp,
                        avObject.getBoolean("invalid"),
                        avObject.getString("name"),
                        avObject.objectId,
                        pa,
                        pd,
                        pokemonName,
                        sa,
                        sd,
                        speed,
                        avObject.updatedAt
                    )
                    if (findFirst == null) {
                        db.save()
                    } else {
                        db.update(findFirst.id)
                    }
                }
            }

        })
    }

    private fun updatePokemon() {
        val dbPokemon = LitePal.order("updatedAt desc").findFirst(DbPokemon::class.java)
        val pokemon = AVQuery<AVObject>("pokemon")
        if (dbPokemon != null) {
            pokemon.whereGreaterThan("updatedAt", dbPokemon.updatedAt)
        }
        pokemon.limit = 500
        pokemon.findInBackground(object : FindCallback<AVObject>() {
            override fun done(avObjects: MutableList<AVObject>?, e: AVException?) {
                e?.printStackTrace()
                if (avObjects == null)
                    return
                for (avObject in avObjects) {
                    val findFirst = LitePal.where("objectId = ?", avObject.objectId)
                        .findFirst(DbPokemon::class.java)
                    val pokemonName = avObject.getString("pokemonName")
                    val hp = avObject.getInt("hp")
                    val pa = avObject.getInt("pa")
                    val pd = avObject.getInt("pd")
                    val sa = avObject.getInt("sa")
                    val sd = avObject.getInt("sd")
                    val speed = avObject.getInt("speed")

                    val db = DbPokemon(
                        avObject.createdAt,
                        avObject.getAVObject<AVObject>("exclusive")?.objectId,
                        hp,
                        avObject.objectId,
                        pa,
                        pd,
                        pokemonName,
                        sa,
                        sd,
                        avObject.getString("skin"),
                        speed,
                        avObject.updatedAt
                    )

                    db.property = avObject.getString("property")
                    db.specialTraining = avObject.getString("specialTraining")
                    db.discount =
                        if (avObject.getDouble("discount") == 0.0) 10.0 else avObject.getDouble(
                            "discount"
                        )
                    db.isLevel = avObject.getBoolean("isLevel")
                    db.red1 = avObject.getString("red1")
                    db.img = avObject.getString("img")
                    db.st2 = avObject.getString("st2")
                    db.skinImg = avObject.getString("skinImg")
                    if (findFirst == null) {
                        db.save()
                    } else {
                        db.update(findFirst.id)
                    }


                }
                Log.d("DataIntentService", "更新数据完毕")
            }

        })
    }

    private fun updateSkill() {
        val dbSkillDo =
            LitePal.order("updatedAt desc").findFirst(DbSkillDo::class.java)
        val skill = AVQuery<AVObject>("skill")
        if (dbSkillDo != null) {
            skill.whereGreaterThan("updatedAt", dbSkillDo.updatedAt)
        }
        skill.findInBackground(object : FindCallback<AVObject>() {
            override fun done(avObjects: MutableList<AVObject>?, e: AVException?) {
                e?.printStackTrace()
                if (avObjects == null)
                    return
                for (avObject in avObjects) {
                    val findFirst = LitePal.where("objectId = ?", avObject.objectId)
                        .findFirst(DbSkillDo::class.java)

                    val db = DbSkillDo(avObject)
                    if (findFirst == null) {
                        db.save()
                    } else {
                        db.update(findFirst.id)
                    }
                }
            }
        })
    }


    private fun updateSuperSkill() {
        val dbSkillDo =
            LitePal.order("updatedAt desc").findFirst(DbSuperSkillDo::class.java)
        val skill = AVQuery<AVObject>("superSkill")
        if (dbSkillDo != null) {
            skill.whereGreaterThan("updatedAt", dbSkillDo.updatedAt)
        }
        skill.findInBackground(object : FindCallback<AVObject>() {
            override fun done(avObjects: MutableList<AVObject>?, e: AVException?) {
                e?.printStackTrace()
                if (avObjects == null)
                    return
                for (avObject in avObjects) {
                    val findFirst = LitePal.where("objectId = ?", avObject.objectId)
                        .findFirst(DbSuperSkillDo::class.java)

                    val db = DbSuperSkillDo(avObject)
                    if (findFirst == null) {
                        db.save()
                    } else {
                        db.update(findFirst.id)
                    }
                }
            }
        })
    }

    private fun updateCharacteristic() {
        val dbSkillDo =
            LitePal.order("updatedAt desc").findFirst(DbCharacteristicDo::class.java)
        val skill = AVQuery<AVObject>("characteristic")
        if (dbSkillDo != null) {
            skill.whereGreaterThan("updatedAt", dbSkillDo.updatedAt)
        }
        skill.findInBackground(object : FindCallback<AVObject>() {
            override fun done(avObjects: MutableList<AVObject>?, e: AVException?) {
                e?.printStackTrace()
                if (avObjects == null)
                    return
                for (avObject in avObjects) {
                    val findFirst = LitePal.where("objectId = ?", avObject.objectId)
                        .findFirst(DbCharacteristicDo::class.java)

                    val db = DbCharacteristicDo(avObject)
                    if (findFirst == null) {
                        db.save()
                    } else {
                        db.update(findFirst.id)
                    }
                }
            }
        })
    }

    private fun updateProp() {
        val dbSkillDo =
            LitePal.order("updatedAt desc").findFirst(DbPropDo::class.java)
        val skill = AVQuery<AVObject>("prop")
        if (dbSkillDo != null) {
            skill.whereGreaterThan("updatedAt", dbSkillDo.updatedAt)
        }
        skill.findInBackground(object : FindCallback<AVObject>() {
            override fun done(avObjects: MutableList<AVObject>?, e: AVException?) {
                e?.printStackTrace()
                if (avObjects == null)
                    return
                for (avObject in avObjects) {
                    val findFirst = LitePal.where("objectId = ?", avObject.objectId)
                        .findFirst(DbPropDo::class.java)

                    val db = DbPropDo(avObject)
                    if (findFirst == null) {
                        db.save()
                    } else {
                        db.update(findFirst.id)
                    }
                }
            }
        })
    }

    private fun saveExclusive() {
        LitePal.deleteAll(DbExclusive::class.java)
        LitePal.deleteAll(DbPokemon::class.java)
        val exclusiveList = readJson<List<ExclusiveJsonDo>>(
            R.raw.exclusive,
            object : TypeToken<List<ExclusiveJsonDo>>() {}.type
        )
        for (ex in exclusiveList) {
            DbExclusive(
                ex.createdAt,
                ex.effect,
                ex.hp,
                ex.invalid,
                ex.name,
                ex.objectId,
                ex.pa,
                ex.pd,
                ex.pokemonName,
                ex.sa,
                ex.sd,
                ex.speed,
                ex.updatedAt
            ).save()
        }

    }

    private fun <T> readJson(raw: Int, type: Type): T {
        val stream = resources.openRawResource(raw)
        return stream.buffered().reader().use { reader -> Gson().fromJson(reader.readText(), type) }
    }

    private fun saveSuperSkill() {
        val pokemonList = readJson<List<SuperSkillJsonDo>>(
            R.raw.super_skill,
            object : TypeToken<List<SuperSkillJsonDo>>() {}.type
        )

        for (poke in pokemonList) {
            DbSuperSkillDo(poke).save()
        }
    }

    private fun saveSkill() {
        val pokemonList = readJson<List<SkillJsonDo>>(
            R.raw.skill,
            object : TypeToken<List<SkillJsonDo>>() {}.type
        )

        for (poke in pokemonList) {
            DbSkillDo(poke).save()
        }
    }

    private fun saveCharacteristic() {
        val pokemonList = readJson<List<CharacteristicJsonDo>>(
            R.raw.characteristic,
            object : TypeToken<List<CharacteristicJsonDo>>() {}.type
        )

        for (poke in pokemonList) {
            DbCharacteristicDo(poke).save()
        }
    }

    private fun saveProp() {
        val pokemonList = readJson<List<PropJsonDo>>(
            R.raw.prop,
            object : TypeToken<List<PropJsonDo>>() {}.type
        )

        for (poke in pokemonList) {
            DbPropDo(poke).save()
        }
    }


    private fun savePokemon() {
        val pokemonList = readJson<List<PokemonJsonDo>>(
            R.raw.pokemon,
            object : TypeToken<List<PokemonJsonDo>>() {}.type
        )

        for (poke in pokemonList) {
            DbPokemon(poke).save()
        }

        Log.d("DataIntentService", "读取数据完毕")
    }

    private fun saveFestivalEnvoy() {
        LitePal.deleteAll(DbFestivalEnvoyDo::class.java)
        val exclusiveList = readJson<List<FestuvaEnvoyJsonDo>>(
            R.raw.festivalenvoy,
            object : TypeToken<List<FestuvaEnvoyJsonDo>>() {}.type
        )
        for (ex in exclusiveList) {
            DbFestivalEnvoyDo(
                ex.question,
                ex.updatedAt,
                ex.answer,
                ex.objectId,
                ex.createdAt
            ).save()
        }
    }

    fun updateFestivalEnvoy() {
        val dbFestivalEnvoyDo =
            LitePal.order("updatedAt desc").findFirst(DbFestivalEnvoyDo::class.java)
        val pokemon = AVQuery<AVObject>("festivalEnvoy")
        if (dbFestivalEnvoyDo != null) {
            pokemon.whereGreaterThan("updatedAt", dbFestivalEnvoyDo.updatedAt)
        }
        pokemon.findInBackground(object : FindCallback<AVObject>() {
            override fun done(avObjects: MutableList<AVObject>?, e: AVException?) {
                e?.printStackTrace()
                if (avObjects == null)
                    return
                for (avObject in avObjects) {
                    val findFirst = LitePal.where("objectId = ?", avObject.objectId)
                        .findFirst(DbFestivalEnvoyDo::class.java)

                    val db = DbFestivalEnvoyDo(
                        avObject.getString("question"),
                        avObject.updatedAt,
                        avObject.getString("answer"),
                        avObject.objectId,
                        avObject.createdAt
                    )
                    if (findFirst == null) {
                        db.save()
                    } else {
                        db.update(findFirst.id)
                    }

                }
            }

        })
    }
}
